/**
 * Swagger文档解析工具
 * 用于根据Swagger文档生成接口信息和枚举信息
 */

/**
 * Swagger解析器类
 */
export class SwaggerParser {
  constructor(swaggerDoc) {
    this.doc = swaggerDoc;
    this.paths = swaggerDoc.paths || {};
    this.definitions = swaggerDoc.definitions || {};
    this.components = swaggerDoc.components || {};
    this.schemas = this.components.schemas || {};
  }

  /**
   * 解析所有API接口
   * @returns {Array} 接口信息数组
   */
  parseApis() {
    const apis = [];

    for (const [path, pathItem] of Object.entries(this.paths)) {
      for (const [method, operation] of Object.entries(pathItem)) {
        if (typeof operation === 'object' && operation.operationId) {
          const api = this.parseApi(path, method, operation);
          apis.push(api);
        }
      }
    }

    return apis;
  }

  /**
   * 解析单个API接口
   * @param {string} path - 接口路径
   * @param {string} method - HTTP方法
   * @param {Object} operation - 操作对象
   * @returns {Object} 解析后的接口信息
   */
  parseApi(path, method, operation) {
    const parameters = this.parseParameters(operation.parameters || []);
    const requestBody = this.parseRequestBody(operation.requestBody);
    const responses = this.parseResponses(operation.responses || {});

    return {
      operationId: operation.operationId,
      summary: operation.summary || '',
      description: operation.description || '',
      tags: operation.tags || [],
      method: method.toUpperCase(),
      path: this.normalizePath(path),
      parameters,
      requestBody,
      responses,
      deprecated: operation.deprecated || false,
      security: operation.security || [],
    };
  }

  /**
   * 解析参数
   * @param {Array} parameters - 参数数组
   * @returns {Array} 解析后的参数
   */
  parseParameters(parameters) {
    return parameters.map(param => ({
      name: param.name,
      in: param.in, // query, path, header, cookie
      required: param.required || false,
      description: param.description || '',
      type: this.getTypeFromSchema(param.schema),
      example: param.example,
      enum: this.extractEnum(param.schema),
    }));
  }

  /**
   * 解析请求体
   * @param {Object} requestBody - 请求体对象
   * @returns {Object} 解析后的请求体
   */
  parseRequestBody(requestBody) {
    if (!requestBody) {
      return null;
    }

    const content = requestBody.content || {};
    const mediaTypes = Object.keys(content);

    return {
      required: requestBody.required || false,
      description: requestBody.description || '',
      contentTypes: mediaTypes,
      schemas: mediaTypes.map(type => ({
        contentType: type,
        schema: this.parseSchema(content[type].schema),
      })),
    };
  }

  /**
   * 解析响应
   * @param {Object} responses - 响应对象
   * @returns {Object} 解析后的响应
   */
  parseResponses(responses) {
    const result = {};

    for (const [statusCode, response] of Object.entries(responses)) {
      const content = response.content || {};
      const mediaTypes = Object.keys(content);

      result[statusCode] = {
        description: response.description || '',
        contentTypes: mediaTypes,
        schemas: mediaTypes.map(type => ({
          contentType: type,
          schema: this.parseSchema(content[type].schema),
        })),
      };
    }

    return result;
  }

  /**
   * 解析Schema
   * @param {Object} schema - Schema对象
   * @returns {Object} 解析后的Schema
   */
  parseSchema(schema) {
    if (!schema) {
      return null;
    }

    return {
      type: schema.type || 'object',
      properties: this.parseProperties(schema.properties || {}),
      required: schema.required || [],
      enum: this.extractEnum(schema),
      items: schema.items ? this.parseSchema(schema.items) : null,
      allOf: schema.allOf ? schema.allOf.map(s => this.parseSchema(s)) : null,
      oneOf: schema.oneOf ? schema.oneOf.map(s => this.parseSchema(s)) : null,
      anyOf: schema.anyOf ? schema.anyOf.map(s => this.parseSchema(s)) : null,
      description: schema.description || '',
      example: schema.example,
      format: schema.format,
      minimum: schema.minimum,
      maximum: schema.maximum,
      minLength: schema.minLength,
      maxLength: schema.maxLength,
      pattern: schema.pattern,
    };
  }

  /**
   * 解析属性
   * @param {Object} properties - 属性对象
   * @returns {Object} 解析后的属性
   */
  parseProperties(properties) {
    const result = {};

    for (const [name, prop] of Object.entries(properties)) {
      result[name] = this.parseSchema(prop);
    }

    return result;
  }

  /**
   * 从Schema中提取类型
   * @param {Object} schema - Schema对象
   * @returns {string} 类型字符串
   */
  getTypeFromSchema(schema) {
    if (!schema) {
      return 'any';
    }

    if (schema.type) {
      return schema.type;
    }

    if (schema.$ref) {
      return this.getRefType(schema.$ref);
    }

    if (schema.enum) {
      return 'enum';
    }

    return 'any';
  }

  /**
   * 获取引用类型
   * @param {string} ref - 引用字符串
   * @returns {string} 类型名称
   */
  getRefType(ref) {
    const parts = ref.split('/');
    return parts[parts.length - 1];
  }

  /**
   * 提取枚举值
   * @param {Object} schema - Schema对象
   * @returns {Array} 枚举值数组
   */
  extractEnum(schema) {
    if (!schema) {
      return null;
    }

    if (schema.enum) {
      return schema.enum;
    }

    if (schema.$ref) {
      const refSchema = this.getSchemaByRef(schema.$ref);
      return refSchema ? this.extractEnum(refSchema) : null;
    }

    return null;
  }

  /**
   * 根据引用获取Schema
   * @param {string} ref - 引用字符串
   * @returns {Object} Schema对象
   */
  getSchemaByRef(ref) {
    const parts = ref.split('/');
    const name = parts[parts.length - 1];

    return this.schemas[name] || this.definitions[name];
  }

  /**
   * 标准化路径
   * @param {string} path - 原始路径
   * @returns {string} 标准化后的路径
   */
  normalizePath(path) {
    return path.replace(/\{([^}]+)\}/g, ':$1');
  }

  /**
   * 解析所有枚举
   * @returns {Array} 枚举信息数组
   */
  parseEnums() {
    const enums = [];

    // 从definitions中查找枚举
    for (const [name, schema] of Object.entries(this.definitions)) {
      const enumValues = this.extractEnum(schema);
      if (enumValues) {
        enums.push({
          name,
          values: enumValues,
          description: schema.description || '',
          type: schema.type || 'string',
        });
      }
    }

    // 从components.schemas中查找枚举
    for (const [name, schema] of Object.entries(this.schemas)) {
      const enumValues = this.extractEnum(schema);
      if (enumValues) {
        enums.push({
          name,
          values: enumValues,
          description: schema.description || '',
          type: schema.type || 'string',
        });
      }
    }

    return enums;
  }

  /**
   * 生成TypeScript类型定义
   * @returns {string} TypeScript类型定义字符串
   */
  generateTypeScriptTypes() {
    let types = '// 自动生成的TypeScript类型定义\n\n';

    // 生成枚举类型
    const enums = this.parseEnums();
    for (const enumInfo of enums) {
      types += `export enum ${enumInfo.name} {\n`;
      for (const value of enumInfo.values) {
        const key =
          typeof value === 'string'
            ? value.toUpperCase().replace(/[^A-Z0-9_]/g, '_')
            : value;
        types += `  ${key} = '${value}',\n`;
      }
      types += '}\n\n';
    }

    // 生成接口类型
    for (const [name, schema] of Object.entries(this.schemas)) {
      if (schema.type === 'object' && schema.properties) {
        types += `export interface ${name} {\n`;
        for (const [propName, propSchema] of Object.entries(
          schema.properties
        )) {
          const isRequired =
            schema.required && schema.required.includes(propName);
          const optional = isRequired ? '' : '?';
          const type = this.getTypeScriptType(propSchema);
          types += `  ${propName}${optional}: ${type};\n`;
        }
        types += '}\n\n';
      }
    }

    return types;
  }

  /**
   * 获取TypeScript类型
   * @param {Object} schema - Schema对象
   * @returns {string} TypeScript类型字符串
   */
  getTypeScriptType(schema) {
    if (!schema) {
      return 'any';
    }

    if (schema.type === 'array') {
      const itemType = this.getTypeScriptType(schema.items);
      return `${itemType}[]`;
    }

    if (schema.type === 'object') {
      return 'object';
    }

    if (schema.enum) {
      return schema.enum.map(v => `'${v}'`).join(' | ');
    }

    if (schema.$ref) {
      return this.getRefType(schema.$ref);
    }

    const typeMap = {
      string: 'string',
      number: 'number',
      integer: 'number',
      boolean: 'boolean',
      array: 'any[]',
      object: 'object',
    };

    return typeMap[schema.type] || 'any';
  }

  /**
   * 生成API调用方法
   * @returns {string} API调用方法字符串
   */
  generateApiMethods() {
    const apis = this.parseApis();
    let methods = '// 自动生成的API调用方法\n\n';

    for (const api of apis) {
      const methodName = this.camelCase(api.operationId);
      const params = this.generateMethodParams(api);
      const returnType = this.generateReturnType(api);

      methods += `export const ${methodName} = async (${params}): Promise<${returnType}> => {\n`;
      methods += `  return httpClient.${api.method.toLowerCase()}('${api.path}', ${this.generateMethodBody(api)});\n`;
      methods += '};\n\n';
    }

    return methods;
  }

  /**
   * 生成方法参数
   * @param {Object} api - API信息
   * @returns {string} 参数字符串
   */
  generateMethodParams(api) {
    const params = [];

    // 路径参数
    const pathParams = api.parameters.filter(p => p.in === 'path');
    if (pathParams.length > 0) {
      const pathParamObj = pathParams.reduce((acc, param) => {
        acc[param.name] = `${this.getTypeScriptType({ type: param.type })}`;
        return acc;
      }, {});
      params.push(
        `pathParams: { ${Object.entries(pathParamObj)
          .map(([k, v]) => `${k}: ${v}`)
          .join(', ')} }`
      );
    }

    // 查询参数
    const queryParams = api.parameters.filter(p => p.in === 'query');
    if (queryParams.length > 0) {
      const queryParamObj = queryParams.reduce((acc, param) => {
        acc[param.name] = `${this.getTypeScriptType({ type: param.type })}`;
        return acc;
      }, {});
      params.push(
        `queryParams?: { ${Object.entries(queryParamObj)
          .map(([k, v]) => `${k}?: ${v}`)
          .join(', ')} }`
      );
    }

    // 请求体
    if (api.requestBody) {
      const bodyType = api.requestBody.schemas[0]?.schema
        ? this.getTypeScriptType(api.requestBody.schemas[0].schema)
        : 'any';
      params.push(`body?: ${bodyType}`);
    }

    return params.join(', ');
  }

  /**
   * 生成返回类型
   * @param {Object} api - API信息
   * @returns {string} 返回类型字符串
   */
  generateReturnType(api) {
    const successResponse =
      api.responses['200'] ||
      api.responses['201'] ||
      Object.values(api.responses)[0];
    if (successResponse && successResponse.schemas[0]) {
      return this.getTypeScriptType(successResponse.schemas[0].schema);
    }
    return 'any';
  }

  /**
   * 生成方法体
   * @param {Object} api - API信息
   * @returns {string} 方法体字符串
   */
  generateMethodBody(api) {
    const parts = [];

    if (api.requestBody) {
      parts.push('body');
    }

    const queryParams = api.parameters.filter(p => p.in === 'query');
    if (queryParams.length > 0) {
      parts.push('queryParams');
    }

    return parts.join(', ');
  }

  /**
   * 转换为驼峰命名
   * @param {string} str - 原始字符串
   * @returns {string} 驼峰命名字符串
   */
  camelCase(str) {
    return str.replace(/([-_][a-z])/gi, $1 =>
      $1.toUpperCase().replace('-', '').replace('_', '')
    );
  }
}

/**
 * 从URL加载Swagger文档
 * @param {string} url - Swagger文档URL
 * @returns {Promise<SwaggerParser>} Swagger解析器实例
 */
export async function loadSwaggerFromUrl(url) {
  try {
    const response = await fetch(url);
    const swaggerDoc = await response.json();
    return new SwaggerParser(swaggerDoc);
  } catch (error) {
    throw new Error(
      `Failed to load Swagger document from ${url}: ${error.message}`
    );
  }
}

/**
 * 从本地文件加载Swagger文档
 * @param {string} filePath - 文件路径
 * @returns {Promise<SwaggerParser>} Swagger解析器实例
 */
export async function loadSwaggerFromFile(filePath) {
  try {
    const fs = await import('fs');
    const content = fs.readFileSync(filePath, 'utf8');
    const swaggerDoc = JSON.parse(content);
    return new SwaggerParser(swaggerDoc);
  } catch (error) {
    throw new Error(
      `Failed to load Swagger document from ${filePath}: ${error.message}`
    );
  }
}

/**
 * 生成完整的API客户端代码
 * @param {SwaggerParser} parser - Swagger解析器实例
 * @returns {string} 完整的API客户端代码
 */
export function generateApiClient(parser) {
  const types = parser.generateTypeScriptTypes();
  const methods = parser.generateApiMethods();

  return `${types}\n${methods}`;
}

/**
 * 导出默认实例创建函数
 */
export default SwaggerParser;
